﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ComponentModel;
using System.Diagnostics;

namespace VuzixSample.model.snes
{
    public class SnesHeaderData : INotifyPropertyChanged
    {
        private
            //http://www.mess.org/
            //src/mess/machine/snescart.c 
            //for country codes
            const string UNK = "unknown";
            string[] companies =
            {
            /* 0*/	"Invalid", "Nintendo", "Ajinomoto", "Imagineer-Zoom", "Chris Gray Enterprises Inc.", "Zamuse", "Falcom", UNK,
            /* 8*/	"Capcom", "HOT-B", "Jaleco", "Coconuts", "Rage Software", "Micronet", "Technos", "Mebio Software",
            /*10*/	"SHOUEi System", "Starfish", "Gremlin Graphics", "Electronic Arts", "NCS / Masaya", "COBRA Team", "Human/Field", "KOEI",
            /*18*/	"Hudson Soft", "Game Village", "Yanoman", UNK, "Tecmo", UNK, "Open System", "Virgin Games",
            /*20*/	"KSS", "Sunsoft", "POW", "Micro World", UNK, UNK, "Enix", "Loriciel/Electro Brain",
            /*28*/	"Kemco", "Seta Co.,Ltd.", "Culture Brain", "Irem Japan", "Pal Soft", "Visit Co.,Ltd.", "INTEC Inc.", "System Sacom Corp.",
            /*30*/	"Viacom New Media", "Carrozzeria", "Dynamic", "Nintendo", "Magifact", "Hect", UNK, UNK,
            /*38*/	"Capcom Europe", "Accolade Europe", UNK, "Arcade Zone", "Empire Software", "Loriciel", "Gremlin Graphics", UNK,
            /*40*/	"Seika Corp.", "UBI Soft", UNK, UNK, "LifeFitness Exertainment", UNK, "System 3", "Spectrum Holobyte",
            /*48*/	UNK, "Irem", UNK, "Raya Systems/Sculptured Software", "Renovation Products", "Malibu Games/Black Pearl", UNK, "U.S. Gold",
            /*50*/	"Absolute Entertainment", "Acclaim", "Activision", "American Sammy", "GameTek", "Hi Tech Expressions", "LJN Toys", UNK,
            /*58*/	UNK, UNK, "Mindscape", "Romstar, Inc.", UNK, "Tradewest", UNK, "American Softworks Corp.",
            /*60*/	"Titus", "Virgin Interactive Entertainment", "Maxis", "Origin/FCI/Pony Canyon", UNK, UNK, UNK, "Ocean",
            /*68*/	UNK, "Electronic Arts", UNK, "Laser Beam", UNK, UNK, "Elite", "Electro Brain",
            /*70*/	"Infogrames", "Interplay", "LucasArts", "Parker Brothers", "Konami", "STORM", UNK, UNK,
            /*78*/	"THQ Software", "Accolade Inc.", "Triffix Entertainment", UNK, "Microprose", UNK, UNK, "Kemco",
            /*80*/	"Misawa", "Teichio", "Namco Ltd.", "Lozc", "Koei", UNK, "Tokuma Shoten Intermedia", "Tsukuda Original",
            /*88*/	"DATAM-Polystar", UNK, UNK, "Bullet-Proof Software", "Vic Tokai", UNK, "Character Soft", "I\'\'Max",
            /*90*/	"Takara", "CHUN Soft", "Video System Co., Ltd.", "BEC", UNK, "Varie", "Yonezawa / S'Pal Corp.", "Kaneco",
            /*98*/	UNK, "Pack in Video", "Nichibutsu", "TECMO", "Imagineer Co.", UNK, UNK, UNK,
            /*a0*/	"Telenet", "Hori", UNK, UNK, "Konami", "K.Amusement Leasing Co.", UNK, "Takara",
            /*a8*/	UNK, "Technos Jap.", "JVC", UNK, "Toei Animation", "Toho", UNK, "Namco Ltd.",
            /*b0*/	"Media Rings Corp.", "ASCII Co. Activison", "Bandai", UNK, "Enix America", UNK, "Halken", UNK,
            /*b8*/	UNK, UNK, "Culture Brain", "Sunsoft", "Toshiba EMI", "Sony Imagesoft", UNK, "Sammy",
            /*c0*/	"Taito", UNK, "Kemco", "Square", "Tokuma Soft", "Data East", "Tonkin House", UNK,
            /*c8*/	"KOEI", UNK, "Konami USA", "NTVIC", UNK, "Meldac", "Pony Canyon", "Sotsu Agency/Sunrise",
            /*d0*/	"Disco/Taito", "Sofel", "Quest Corp.", "Sigma", "Ask Kodansha Co., Ltd.", UNK, "Naxat", UNK,
            /*d8*/	"Capcom Co., Ltd.", "Banpresto", "Tomy", "Acclaim", UNK, "NCS", "Human Entertainment", "Altron",
            /*e0*/	"Jaleco", UNK, "Yutaka", UNK, "T&ESoft", "EPOCH Co.,Ltd.", UNK, "Athena",
            /*e8*/	"Asmik", "Natsume", "King Records", "Atlus", "Sony Music Entertainment", UNK, "IGS", UNK,
            /*f0*/	UNK, "Motown Software", "Left Field Entertainment", "Beam Software", "Tec Magik", UNK, UNK, UNK,
            /*f8*/	UNK, "Cybersoft", UNK, "Psygnosis", UNK, UNK, "Davidson", UNK
            };

#region properties

        private string _name = "empty header";
        public string name
        {
            get
            {
                return _name;
            }
            set
            {
                _name = value;
                NotifyPropertyChanged("name");
            }
        }

        private uint _layout;
        public uint layout 
        {
            get
            {
                return _layout;
            }
            set
            {
                _layout = value;

                NotifyPropertyChanged("layout");
                NotifyPropertyChanged("layoutAsString");
            }
        }

        public string layoutAsString
        {
            get //read only
            {
                string asString;
                switch (_layout)
                {
                    case 0x20:
                        asString = "LoRom";
                        break;
                    case 0x21:
                        asString = "HiRom";
                        break;
                    case 0x30:
                        asString = "Fast LoRom";
                        break;
                    case 0x31:
                        asString = "Fast HiRom";
                        break;
                    default:
                        asString = "unknown: " + _layout.ToString("X8");
                        break;
                }
                return asString;
            }
        }

        private uint _type;
        public uint type 
        {
            get
            {
                return _type;
            }
            set
            {
                _type = value;
                NotifyPropertyChanged("type");
                NotifyPropertyChanged("typeAsString");
            }
        }
        //http://romhack.wikia.com/wiki/SNES_header
        public string typeAsString
        {
            get //read only
            {
                string asString;
                switch (_type)
                {
                    case 0x00:
                        asString = "ROM Only";
                        break;
                    case 0x02:
                        asString = "ROM With Save";
                        break;
                    case 0x13:
                    case 0x14:
                        asString = "Super FX no battery";
                        break;
                    case 0x15:
                    case 0x1a:
                        asString = "Super FX With Save";
                        break;
                    case 0x34:
                    case 0x35:
                        asString = "SA-1";
                        break;
                    default:
                        asString = "unknown: " + _type.ToString("X2");
                        break;
                }
                return asString;
            }
        }

        private uint _romSize;
        public uint romSize 
        {
            get
            {
                //return bytes
                string hexValue = _romSize + "0000";
                return Convert.ToUInt32(hexValue, 16);
            }
            set
            {
                _romSize = value;
                NotifyPropertyChanged("romSize");
            }
        }

        private uint _ramSize;
        public uint ramSize 
        {
            get
            {
                //return bytes
                string hexValue = _ramSize + "0000";
                return Convert.ToUInt32(hexValue, 16);
            }
            set
            {
                _ramSize = value;
                NotifyPropertyChanged("ramSize");
            }
        }

        private uint _countryCode;
        public uint countryCode 
        {
            get
            {
                return _countryCode;
            }
            set
            {
                _countryCode = value;
                NotifyPropertyChanged("countryCode");
                NotifyPropertyChanged("countryCodeAsString");
            }
        }

        //http://www.mess.org/
        //src/mess/machine/snescart.c 
        //for country codes
        public string countryCodeAsString
        {
            get //read only
            {
                string asString;
                switch (_countryCode)
                {
                    case 0x00:
                        asString = "Japan (NTSC)";
                        break;
                    case 0x01:
                        asString = "USA & Canada (NTSC)";
                        break;
                    case 0x02:
                        asString = "Europe, Oceania & Asia (PAL)";
                        break;
                    case 0x03:
                        asString = "Sweden (PAL)";
                        break;
                    case 0x04:
                        asString = "Finland (PAL)";
                        break;
                    case 0x05:
                        asString = "Denmark (PAL)";
                        break;
                    case 0x06:
                        asString = "France (PAL)";
                        break;
                    case 0x07:
                        asString = "Holland (PAL)";
                        break;
                    case 0x08:
                        asString = "Spain (PAL)";
                        break;
                    case 0x09:
                        asString = "Germany, Austria & Switzerland (PAL)";
                        break;
                    case 0x0A:
                        asString = "Italy (PAL)";
                        break;
                    case 0x0B:
                        asString = "Hong Kong & China (PAL)";
                        break;
                    case 0x0C:
                        asString = "Indonesia (PAL)";
                        break;
                    case 0x0D:
                        asString = "South Korea (NTSC)";
                        break;
                    default:
                        asString = "unknown: " + _type.ToString("X2");
                        break;
                }
                return asString;
            }
        }

        private uint _licenceCode;
        public uint licenceCode 
        {
            get
            {
                return _licenceCode;
            }
            set
            {
                _licenceCode = value;
                NotifyPropertyChanged("licenceCode");
                NotifyPropertyChanged("licenceCodeAsString");
            }
        }
        public string licenceCodeAsString
        {
            get //readonly
            {
                Debug.WriteLine(_licenceCode);
                return companies[_licenceCode];
            }
        }

        private uint _versionNumber;
        public uint versionNumber
        {
            get
            {
                return _versionNumber;
            }
            set
            {
                _versionNumber = value;
                NotifyPropertyChanged("versionNumber");
            }
        }

#endregion properties

        public event PropertyChangedEventHandler PropertyChanged;
        protected void NotifyPropertyChanged(string sProp)
        {
            if (PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs(sProp));
            }
        }

        public void Clear()
        {
            _name = "empty header";
            _layout = 0;
            _type = 0;
            _romSize = 0;
            _ramSize = 0;
            _countryCode = 0;
            _licenceCode = 0;
            _versionNumber = 0;
        }
    }
}
